package com.lin.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.google.gson.Gson;
import com.lin.auth.common.config.CustomBusinessException;
import com.lin.auth.common.enums.AuthUserStatusEnum;
import com.lin.auth.common.enums.IsDeletedFlagEnum;
import com.lin.auth.domain.constants.AuthConstant;
import com.lin.auth.domain.convert.AuthUserBOConverter;
import com.lin.auth.domain.entity.AuthUserBO;
import com.lin.auth.domain.redis.RedisUtil;
import com.lin.auth.domain.service.AuthUserDomainService;
import com.lin.auth.infra.basic.entity.*;
import com.lin.auth.infra.basic.service.*;
import com.mysql.cj.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    private static final String LOGIN_PREFIX = "loginCode";


    @Resource
    private AuthUserService authUserService;

    @Resource
    private AuthUserRoleService authUserRoleService;

    @Resource
    private AuthRoleService authRoleService;

    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private AuthRolePermissionService authRolePermissionService;

    @Resource
    private RedisUtil redisUtil;

    private String authPermissionPrefix = "auth.permission";

    private String authRolePrefix = "auth.role";

    private String salt = "chicken";

    @Override
    public Boolean register(AuthUserBO authUserBO) {
        // 判断账号是否被注册
        registerValidate(authUserBO);
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), salt));
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        Integer count = authUserService.insert(authUser);
        //建立一个初步的角色的关联
        AuthRole authRole = new AuthRole();
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        Long roleId = roleResult.getId();
        Long userId = authUser.getId();
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUserRoleService.insert(authUserRole);
        //要把当前用户的角色和权限都刷到我们的redis里
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        redisUtil.set(roleKey, new Gson().toJson(roleList));

        AuthRolePermission authRolePermission = new AuthRolePermission();
        authRolePermission.setRoleId(roleId);
        List<AuthRolePermission> rolePermissionList = authRolePermissionService.
                queryByCondition(authRolePermission);

        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId).collect(Collectors.toList());
        //根据roleId查权限
        List<AuthPermission> permissionList = authPermissionService.queryByRoleList(permissionIdList);
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        redisUtil.set(permissionKey, new Gson().toJson(permissionList));
        return count > 0;
    }

    /**
     * 登陆
     *
     * @param validCode
     * @return
     */
    @Override
    public SaTokenInfo doLogin(String validCode) {
        String key = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(key);
        if (StringUtils.isNullOrEmpty(openId)) {
            throw new RuntimeException("验证码已失效");
        }
        // 判断用户是否已经注册
        AuthUser authUser = new AuthUser();
        authUser.setUserName(openId);
        AuthUser byFilter = authUserService.findByFilter(authUser);

        if (Objects.isNull(byFilter)) {
            AuthUserBO authUserBO = new AuthUserBO();
            authUserBO.setUserName(openId);
            this.register(authUserBO);
        }

        StpUtil.login(openId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return tokenInfo;
    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> userList = authUserService.queryByCondition(authUser);
        if(CollectionUtils.isEmpty(userList)){
            return new AuthUserBO();
        }
        AuthUser user = userList.get(0);
        return AuthUserBOConverter.INSTANCE.convertEntityToBO(user);
    }

    /**
     * 更新用户
     *
     * @param authUserBO
     * @return
     */
    @Override
    public Object update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        return authUserService.update(authUser);
    }

    /**
     * 删除用户
     * @param authUserBO
     * @return
     */
    @Override
    public Object deleteUser(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setId(authUserBO.getId());
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        return authUserService.update(authUser);
    }


    private void registerValidate(AuthUserBO authUserBO) {
        AuthUser filter = new AuthUser();
        filter.setUserName(authUserBO.getUserName());
        AuthUser findByUserName = authUserService.findOneByFilter(filter);

        if (Objects.nonNull(findByUserName)) {
            throw new CustomBusinessException("该账号已被注册");
        }
    }
}
